﻿using CodeGenerator.CSharp;
using System.Threading.Tasks;
using Modifier = CodeGenerator.CSharp.Modifiers;

namespace CodeAngel.Domain
{
    public static class DtoExtensionsFileGenerator
    {
        #region CreateDtoExtensionsFileAsync

        /// <summary>
        /// Creates and writes to disk the DTO extension file for the specified Domain.
        /// If this file already exists, it will be overwritten.
        /// </summary>
        public static Task CreateDtoExtensionsFileAsync(this Domain thisDomain)
        {
            return Task.Factory.StartNew(() =>
            {
                DtoExtensionsFileGenerator.WriteToDisk(thisDomain);
            });
        }

        #endregion

        #region WriteToDisk

        /// <summary>
        /// Creates and writes to disk the DtoExtensions.cs file. If this file already exists, 
        /// it will be overwritten.
        /// </summary>
        private static void WriteToDisk(Domain thisDomain)
        {
            var ThisFB = new FileBuilder();
            ThisFB.ProjectName = thisDomain.ServicesProjectName;
            ThisFB.Directory = thisDomain.ServicesExtensionsPath;
            ThisFB.FileName = "DtoExtensions.cs";
            ThisFB.Namespace = thisDomain.ServicesNamespace;

            // Add the using namespaces for this file.
            ThisFB.UsingNamespaces.Add("System");
            ThisFB.UsingNamespaces.Add("System.Collections.Generic");
            ThisFB.UsingNamespaces.Add("System.Configuration");
            ThisFB.UsingNamespaces.Add("System.Data");
            ThisFB.UsingNamespaces.Add("System.Data.SqlClient");
            ThisFB.UsingNamespaces.Add("System.Runtime.Serialization");
            ThisFB.UsingNamespaces.Add(thisDomain.DomainNamespace);
            ThisFB.UsingNamespaces.Add(thisDomain.FrameworkNamespace);

            // Add the DTO class.
            ThisFB.CodeUnits.Add(new DtoExtensionsClassBuilder(thisDomain));

            // Write this file to disk.
            ThisFB.WriteToDisk(OverwriteExistingFile.Yes);
        }

        #endregion

        #region DtoExtensionsClassBuilder

        /// <summary>
        /// Builds the DTOExtensions class - a collection of extension methods
        /// for DTO classes that need access to the full-CLR.
        /// </summary>
        private class DtoExtensionsClassBuilder : ClassBuilder
        {
            #region Constructors

            public DtoExtensionsClassBuilder(Domain thisDomain)
                : base("DtoExtensions", Modifier.PublicStatic)
            {
                this._domain = thisDomain;
                this.Documentation.Summary = "A collection of domain-specific extension methods used to extend DTO funtionality.";
                this.AddCreateSaveParametersProcedure();
                this.AddCreateDeleteParametersProcedure();
                this.AddGetStoredProcedureNameProcedures();
                this.AddCreateDtosFromDataReaderProcedures();
                this.AddGetRemoveDtoProcedure();
                this.AddGetStoredProcedureCommandProcedure();
                this.AddRemoveDtoProcedure();
                //this.AddReadDtoProcedures();
                //this.AddGetColumnIndexProcedure();
            }
            private Domain _domain;

            #endregion

            #region AddCreateSaveParameters

            /// <summary>
            /// Adds the CreateSaveParameters procedure to this class builder.
            /// </summary>
            private void AddCreateSaveParametersProcedure()
            { 
                //
                var ThisRegion = this.AddRegion("CreateSaveParameters");
                var ThisProcedure = ThisRegion.AddProcedure("CreateSaveParameters", Modifier.PublicStatic);
                ThisProcedure.Documentation.Summary = "Creates the parameters used for a save operation for the identified DTO, and adds them to the identified parameters collection.";
                ThisProcedure.Parameters.Add("thisDto", "IDto").IsExtensionParameter = true;
                ThisProcedure.Parameters.Add("parameters", "SqlParameterCollection");

                bool OnFirstEntityDef = true;
                foreach (var thisED in this._domain.EntityDefs)
                {
                    if (OnFirstEntityDef)
                    {
                        OnFirstEntityDef = false;
                        ThisProcedure.Body.Add("if (thisDto is {0})", thisED.ClassNames.Dto());
                    }
                    else
                    {
                        ThisProcedure.Body.Add("else if (thisDto is {0})", thisED.ClassNames.Dto());
                    }

                    ThisProcedure.Body.Add("{");
                    ThisProcedure.Body.Add("    var this{0} = thisDto as {0};", thisED.ClassNames.Dto());
                    foreach (var thisPD in thisED.PropertyDefs.ScalarOrEntityProperties)
                    {
                        int DataLength = thisPD.SqlDataLength > 0 ? thisPD.SqlDataLength.Value : -1;
                        ThisProcedure.Body.Add("    parameters.Add(\"@{0}\", SqlDbType.{1}, {2}, \"{0}\").Value = this{3}.{4};", thisPD.DatabaseColumnName, thisPD.SqlDbType.ToString(), DataLength, thisED.ClassNames.Dto(), thisPD.Names.Field());
                    }
                    ThisProcedure.Body.Add("    var TimeStampParameter = parameters.Add(\"@TimeStamp\", SqlDbType.Timestamp, -1, \"TimeStamp\");");
                    ThisProcedure.Body.Add("    TimeStampParameter.Value = this{0}.TimeStamp;", thisED.ClassNames.Dto());
                    ThisProcedure.Body.Add("    TimeStampParameter.Direction = thisDto.State == DtoChangedState.Modified ? ParameterDirection.InputOutput : ParameterDirection.Output;");
                    ThisProcedure.Body.Add("}");
                }
            }

            #endregion

            #region AddCreateDeleteParametersProcedure

            /// <summary>
            /// Adds the CreateDeleteParameters procedure to this class builder.
            /// </summary>
            private void AddCreateDeleteParametersProcedure()
            {
                var ThisRegion = this.AddRegion("CreateDeleteParameters");
                var ThisProcedure = ThisRegion.AddProcedure("CreateDeleteParameters", Modifier.PublicStatic);
                ThisProcedure.Documentation.Summary = "Creates the parameters used for a delete operation for the identified DTO, and adds them to the identified parameters collection.";
                ThisProcedure.Parameters.Add("thisDto", "IDto").IsExtensionParameter = true;
                ThisProcedure.Parameters.Add("parameters", "SqlParameterCollection");

                bool OnFirstEntityDef = true;
                foreach (var thisED in this._domain.EntityDefs)
                {
                    if (OnFirstEntityDef)
                    {
                        OnFirstEntityDef = false;
                        ThisProcedure.Body.Add("if (thisDto is {0})", thisED.ClassNames.Dto());
                    }
                    else
                    {
                        ThisProcedure.Body.Add("else if (thisDto is {0})", thisED.ClassNames.Dto());
                    }
                    ThisProcedure.Body.Add("{");
                    var thisPD = thisED.PrimaryKeyPropertyDef;
                    ThisProcedure.Body.Add("    var this{0} = thisDto as {0};", thisED.ClassNames.Dto());
                    ThisProcedure.Body.Add("    parameters.Add(\"@{0}\", SqlDbType.UniqueIdentifier, -1, \"{0}\").Value = this{1}.ID;", thisPD.DatabaseColumnName, thisED.ClassNames.Dto());
                    ThisProcedure.Body.Add("}");
                }
            }

            #endregion

            #region AddGetInsertStoredProcedureNameProcedure

            /// <summary>
            /// Adds the GetInsertStoredProcedureName procedure to this class builder.
            /// </summary>
            private void AddGetStoredProcedureNameProcedures()
            {
                var ThisRegion = this.AddRegion("Stored Procedure Names");

                // GetInsertStoredProcedureName
                var GetInsertStoredProcedureNameProcedure = ThisRegion.AddProcedure("GetInsertStoredProcedureName", Modifier.PublicStatic, "string");
                GetInsertStoredProcedureNameProcedure.Documentation.Summary = "Gets the name of the stored procedure used to insert the data from the identified DTO.";
                GetInsertStoredProcedureNameProcedure.Parameters.Add("thisDto", "IDto").IsExtensionParameter = true;
                bool OnFirstEntityDef = true;
                foreach (var thisED in this._domain.EntityDefs)
                {
                    if (OnFirstEntityDef)
                    {
                        OnFirstEntityDef = false;
                        GetInsertStoredProcedureNameProcedure.Body.Add("if (thisDto is {0})", thisED.ClassNames.Dto());
                    }
                    else
                    {
                        GetInsertStoredProcedureNameProcedure.Body.Add("else if (thisDto is {0})", thisED.ClassNames.Dto());
                    }

                    GetInsertStoredProcedureNameProcedure.Body.Add("    return \"{0}\";", thisED.StoredProcedureNames.Insert());
                }
                GetInsertStoredProcedureNameProcedure.Body.Add("else return string.Empty;");

                // GetUpdateStoredProcedureName
                var GetUpdateStoredProcedureNameProcedure = ThisRegion.AddProcedure("GetUpdateStoredProcedureName", Modifier.PublicStatic, "string");
                GetUpdateStoredProcedureNameProcedure.Documentation.Summary = "Gets the name of the stored procedure used to Update the data from the identified DTO.";
                GetUpdateStoredProcedureNameProcedure.Parameters.Add("thisDto", "IDto").IsExtensionParameter = true;
                OnFirstEntityDef = true;
                foreach (var thisED in this._domain.EntityDefs)
                {
                    if (OnFirstEntityDef)
                    {
                        OnFirstEntityDef = false;
                        GetUpdateStoredProcedureNameProcedure.Body.Add("if (thisDto is {0})", thisED.ClassNames.Dto());
                    }
                    else
                    {
                        GetUpdateStoredProcedureNameProcedure.Body.Add("else if (thisDto is {0})", thisED.ClassNames.Dto());
                    }
                    GetUpdateStoredProcedureNameProcedure.Body.Add("    return \"{0}\";", thisED.StoredProcedureNames.Update());
                }
                GetUpdateStoredProcedureNameProcedure.Body.Add("else return string.Empty;");

                // GetDeleteStoredProcedureName
                var GetDeleteStoredProcedureNameProcedure = ThisRegion.AddProcedure("GetDeleteStoredProcedureName", Modifier.PublicStatic, "string");
                GetDeleteStoredProcedureNameProcedure.Documentation.Summary = "Gets the name of the stored procedure used to Delete the data from the identified DTO.";
                GetDeleteStoredProcedureNameProcedure.Parameters.Add("thisDto", "IDto").IsExtensionParameter = true;
                OnFirstEntityDef = true;
                foreach (var thisED in this._domain.EntityDefs)
                {
                    if (OnFirstEntityDef)
                    {
                        OnFirstEntityDef = false;
                        GetDeleteStoredProcedureNameProcedure.Body.Add("if (thisDto is {0})", thisED.ClassNames.Dto());
                    }
                    else
                    {
                        GetDeleteStoredProcedureNameProcedure.Body.Add("else if (thisDto is {0})", thisED.ClassNames.Dto());
                    }
                    GetDeleteStoredProcedureNameProcedure.Body.Add("    return \"{0}\";", thisED.StoredProcedureNames.Delete());
                }
                GetDeleteStoredProcedureNameProcedure.Body.Add("else return string.Empty;");
            }

            #endregion

            #region AddCreateDtosFromDataReaderProcedure

            /// <summary>
            /// Adds the CreateDtosFromDataReader procedure.
            /// </summary>
            private void AddCreateDtosFromDataReaderProcedures()
            {
                var ThisRegion = this.AddRegion("CreateDtosFromDataReader");

                foreach (var ThisED in this._domain.EntityDefs)
                {
                    var ThisProcedure = ThisRegion.AddProcedure(ThisED.ProcedureNames.CreateDtosFromDataReader(), Modifier.InternalStatic);
                    ThisProcedure.Documentation.Summary = "Reads the "  + ThisED.Name + " data from the identifed SqlDataReader, and creates & adds respective new " + ThisED.ClassNames.Dto() + " objects to the identified items collection.";
                    ThisProcedure.Parameters.Add("sqlDataReader", "SqlDataReader").IsExtensionParameter = true;
                    ThisProcedure.Parameters.Add("items", "List<" + ThisED.ClassNames.Dto() + ">");

                    foreach (var ThisPD in ThisED.PropertyDefs.ScalarOrEntityProperties)
                        ThisProcedure.Body.Add("int {0}ColumnIndex = GetColumnIndex(sqlDataReader, \"{0}\");", ThisPD.Names.Field());
                    ThisProcedure.Body.Add("int TimeStampColumnIndex = GetColumnIndex(sqlDataReader, \"TimeStamp\");");
                    ThisProcedure.Body.AddBlankLine();
                    
                    ThisProcedure.Body.Add("while (sqlDataReader.Read())");
                    ThisProcedure.Body.Add("{");
                    ThisProcedure.Body.Add("    var ThisDto = new {0}();", ThisED.ClassNames.Dto());
                    ThisProcedure.Body.Add("    if (TimeStampColumnIndex != -1) ThisDto.TimeStamp = (byte[])sqlDataReader.GetValue(TimeStampColumnIndex);");
                    ThisProcedure.Body.AddBlankLine();
                    foreach (PropertyDef ThisPD in ThisED.PropertyDefs.ScalarOrEntityProperties)
                    {
                        string SqlDataReaderGet = null;
                        if (ThisPD.IsEntityType)
                            SqlDataReaderGet = "GetGuid";
                        else
                            SqlDataReaderGet = ThisPD.SqlDataReaderGet;
                        if (ThisPD.IsNullable)
                        {
                            ThisProcedure.Body.Add("    if ({0}ColumnIndex != -1)", ThisPD.Names.Field());
                            ThisProcedure.Body.Add("    {");
                            ThisProcedure.Body.Add("        if (sqlDataReader.IsDBNull({0}ColumnIndex))", ThisPD.Names.Field());
                            ThisProcedure.Body.Add("            ThisDto.{0} = null;", ThisPD.Names.Field());
                            ThisProcedure.Body.Add("        else");
                            ThisProcedure.Body.Add("            ThisDto.{0} = sqlDataReader.{1}({0}ColumnIndex);", ThisPD.Names.Field(), SqlDataReaderGet);
                            ThisProcedure.Body.Add("    }");
                        }
                        else
                        {
                            ThisProcedure.Body.Add("    if ({0}ColumnIndex != -1) ThisDto.{0} = sqlDataReader.{1}({0}ColumnIndex);", ThisPD.Names.Field(), SqlDataReaderGet);
                        }
                    }
                    ThisProcedure.Body.AddBlankLine();
                    ThisProcedure.Body.Add("    items.Add(ThisDto);");
                    ThisProcedure.Body.Add("}");
                }

                var GetColumnIndexProcedure = ThisRegion.AddProcedure("GetColumnIndex", Modifier.PrivateStatic, "int");
                GetColumnIndexProcedure.Documentation.Summary = "Gets the column index within the identified SqlDataReader for the identified column name.";
                GetColumnIndexProcedure.Parameters.Add("sqlDataReader", "SqlDataReader");
                GetColumnIndexProcedure.Parameters.Add("columnName", "string");

                GetColumnIndexProcedure.Body.Add("int FoundIndex = -1;");
                GetColumnIndexProcedure.Body.Add("for (int columnIndex = 0; columnIndex < sqlDataReader.FieldCount; columnIndex++)");
                GetColumnIndexProcedure.Body.Add("{");
                GetColumnIndexProcedure.Body.Add("  if (sqlDataReader.GetName(columnIndex)==columnName)");
                GetColumnIndexProcedure.Body.Add("  {");
                GetColumnIndexProcedure.Body.Add("      FoundIndex = columnIndex;");
                GetColumnIndexProcedure.Body.Add("      break;");
                GetColumnIndexProcedure.Body.Add("  }");
                GetColumnIndexProcedure.Body.Add("}");
                GetColumnIndexProcedure.Body.Add("return FoundIndex;");

                //}

                ////--------------------------------------------------------------------------------------
                //// GetColumnIndex
                ////--------------------------------------------------------------------------------------
                //var _with9 = this.AddFullClrConditionalCompilation.AddProcedure("GetColumnIndex", AI.Modifier.Private, "int");
                //_with9.Documentation.Summary = "Searches the identified SQL Data Reader for a column with the identified name.  If one is not found, -1 is returned.";
                //_with9.Parameters.Add("sqlDataReader", "SqlDataReader");
                //_with9.Parameters.Add("columnName", "string");
                ////.Parameters.Add("tableName", "string")
                //var _with10 = _with9.Body;
                //_with10.Add("int FoundIndex = -1;");
                //_with10.Add("for (int columnIndex = 0; columnIndex < sqlDataReader.FieldCount; columnIndex++)");
                //_with10.Add("{");
                //_with10.Add("    if (sqlDataReader.GetName(columnIndex)==columnName)");
                //_with10.Add("    {");
                //_with10.Add("        FoundIndex = columnIndex;");
                //_with10.Add("        break;");
                //_with10.Add("    }");
                //_with10.Add("}");
                ////.Add("if (FoundIndex == -1) throw new Exception(""Unable to find column '"" + columnName + ""' in '"" + tableName + ""' table."");")
                //_with10.Add("return FoundIndex;");


                //var _with11 = this.AddFullClrConditionalCompilation.AddProcedure("DeleteDto", AI.Modifier.Internal);
                //_with11.Documentation.Summary = "";
                //_with11.Parameters.Add("dto", "IDto");
                //var _with12 = _with11.Body;
                //bool OnFirstEntity = true;
                //foreach (EntityDef ThisED in this._Domain.EntityDefs) {
                //    if (OnFirstEntity) {
                //        OnFirstEntity = false;
                //        _with12.Add("if (dto is {0})", ThisED.ClassNames.Dto);
                //    } else {
                //        _with12.Add("else if (dto is {0})", ThisED.ClassNames.Dto);
                //    }

                //    _with12.Add("{");
                //    _with12.Add("    var ThisDto = dto as {0};", ThisED.ClassNames.Dto);
                //    _with12.Add("    if (this.Root{0}.Contains(ThisDto))", ThisED.Nm.ToPlural);
                //    _with12.Add("        this.Root{0}.Remove(ThisDto);", ThisED.Nm.ToPlural);
                //    _with12.Add("    else if (this.{0}.Contains(ThisDto))", ThisED.Nm.ToPlural);
                //    _with12.Add("        this.{0}.Remove(ThisDto);", ThisED.Nm.ToPlural);
                //    //.Add("    if (this.Root{0}.Contains(dto as {1}))", ThisED.Nm.ToPlural, ThisED.ClassNames.Dto)
                //    //.Add("        this.Root{0}.Remove(dto as {1});", ThisED.Nm.ToPlural, ThisED.ClassNames.Dto)
                //    //.Add("    else if (this.{0}.Contains(dto as {1}))", ThisED.Nm.ToPlural, ThisED.ClassNames.Dto)
                //    //.Add("        this.{0}.Remove(dto as {1});", ThisED.Nm.ToPlural, ThisED.ClassNames.Dto)
                //    _with12.Add("}");
                //}


            }

            #endregion

            #region AddCreateSaveParameters

            /// <summary>
            /// Adds the CreateSaveParameters procedure to this class builder.
            /// </summary>
            private void AddGetRemoveDtoProcedure()
            {
                var ThisRegion = this.AddRegion("GetDeleteDto");
                var ThisProcedure = ThisRegion.AddProcedure("GetDeleteDto", Modifier.PublicStatic, "IDto");
                ThisProcedure.Documentation.Summary = "Gets appropriate IDto object that can be used to delete the respective record in the database.";
                ThisProcedure.Parameters.Add("className", "string").IsExtensionParameter = true;
                ThisProcedure.Parameters.Add("id", "Guid");

                bool OnFirstEntityDef = true;
                foreach (var thisED in this._domain.EntityDefs)
                {
                    if (OnFirstEntityDef)
                    {
                        OnFirstEntityDef = false;
                        ThisProcedure.Body.Add("if (className == \"{0}\")", thisED.ClassNames.ClassName());
                    }
                    else
                    {
                        ThisProcedure.Body.Add("else if (className == \"{0}\")", thisED.ClassNames.ClassName());
                    }

                    ThisProcedure.Body.Add("{");
                    ThisProcedure.Body.Add("    return new {0}() {{ {1} = id }};", thisED.ClassNames.Dto(), thisED.PrimaryKeyPropertyDef.Names.Field());
                    ThisProcedure.Body.Add("}");
                }
                ThisProcedure.Body.Add("else");
                ThisProcedure.Body.Add("    throw new Exception(\"Unable to determine DTO for class name: \" + className);");
            }

            #endregion

            #region AddGetStoredProcedureCommandProcedure

            /// <summary>
            /// 
            /// </summary>
            private void AddGetStoredProcedureCommandProcedure()
            {
                var ThisRegion = this.AddRegion("GetStoredProcedureCommand");
                var ThisProcedure = ThisRegion.AddProcedure("GetStoredProcedureCommand", Modifier.PublicStatic, "SqlCommand");
                ThisProcedure.Documentation.Summary = "Gets appropriate IDto object that can be used to delete the respective record in the database.";
                ThisProcedure.Parameters.Add("storedProcedureName", "string");
                ThisProcedure.Parameters.Add("filter", "string");
                ThisProcedure.Parameters.Add("userName", "string");
                ThisProcedure.Parameters.Add("password", "string");

                ThisProcedure.Body.Add("string ConnectionString = ConfigurationManager.ConnectionStrings[\"DomainDatabaseConnection\"].ConnectionString;");
                ThisProcedure.Body.Add("var ThisConnection = new SqlConnection(ConnectionString);");
                ThisProcedure.Body.Add("var ThisCommand = new SqlCommand();");
                ThisProcedure.Body.Add("ThisCommand.Connection = ThisConnection;");
                ThisProcedure.Body.Add("ThisCommand.CommandText = storedProcedureName;");
                ThisProcedure.Body.Add("ThisCommand.CommandType = CommandType.StoredProcedure;");
                ThisProcedure.Body.Add("ThisCommand.Parameters.AddWithValue(\"@Filter\", filter);");
                ThisProcedure.Body.Add("ThisCommand.Parameters.AddWithValue(\"@ThisUser\", userName);");
                ThisProcedure.Body.Add("ThisCommand.Parameters.AddWithValue(\"@UserPassword\", password);");
                ThisProcedure.Body.AddBlankLine();
                ThisProcedure.Body.Add("return ThisCommand;");
            }

            #endregion

            #region AddRemoveDtoProcedure

            private void AddRemoveDtoProcedure()
            {
                var ThisProcedure = this.AddRegion("RemoveDto").AddProcedure("RemoveDto", Modifier.PublicStatic);
                ThisProcedure.Documentation.Summary = "Removes the identified DTO from the identified DtoHost";
                ThisProcedure.Parameters.Add("ThisDtoHost", "DtoHost").IsExtensionParameter = true;
                ThisProcedure.Parameters.Add("dto", "IDto");
                bool OnFirstEntity = true;
                foreach (var ThisED in this._domain.EntityDefs)
                {
                    if (OnFirstEntity)
                    {
                        OnFirstEntity = false;
                        ThisProcedure.Body.Add("if (dto is {0})", ThisED.ClassNames.Dto());
                    }
                    else
                    {
                        ThisProcedure.Body.Add("else if (dto is {0})", ThisED.ClassNames.Dto());
                    }

                    ThisProcedure.Body.Add("{");
                    ThisProcedure.Body.Add("    var ThisDto = dto as {0};", ThisED.ClassNames.Dto());
                    ThisProcedure.Body.Add("    if (ThisDtoHost.Root{0}.Contains(ThisDto))", ThisED.Name.ToPlural());
                    ThisProcedure.Body.Add("        ThisDtoHost.Root{0}.Remove(ThisDto);", ThisED.Name.ToPlural());
                    ThisProcedure.Body.Add("    else if (ThisDtoHost.{0}.Contains(ThisDto))", ThisED.Name.ToPlural());
                    ThisProcedure.Body.Add("        ThisDtoHost.{0}.Remove(ThisDto);", ThisED.Name.ToPlural());
                    ThisProcedure.Body.Add("}");

                }

            }

            #endregion

            //#region ReadDto

            //private void AddReadDtoProcedures()
            //{ 
            //    var ThisRegion = this.AddRegion("ReadDto");

            //    foreach (var ThisED in this._domain.EntityDefs)
            //    {
            //        var ThisProcedure = ThisRegion.AddProcedure("Read" + ThisED.Name.ToPlural(), Modifier.Internal);
            //        ThisProcedure.Parameters.Add("sqlDataReader", "SqlDataReader");
            //        string DataType = "List<" + ThisED.ClassNames.Dto() + ">";
            //        ThisProcedure.Parameters.Add("items", DataType);
            //        foreach (PropertyDef ThisPD in ThisED.PropertyDefs.ScalarOrEntityProperties)
            //        {
            //            //.Add("int {0}ColumnIndex = this.GetColumnIndex(sqlDataReader, ""{0}"");", ThisPD.Nm.ToField)
            //            ThisProcedure.Body.Add("int {0}ColumnIndex = this.GetColumnIndex(sqlDataReader, \"{0}\");", ThisPD.DatabaseColumnName);
            //        }
            //        ThisProcedure.Body.Add("int TimeStampColumnIndex = this.GetColumnIndex(sqlDataReader, \"TimeStamp\");");

            //        ThisProcedure.Body.AddBlankLine();
            //        ThisProcedure.Body.Add("while (sqlDataReader.Read())");
            //        ThisProcedure.Body.Add("{");
            //        ThisProcedure.Body.Add("    var ThisDto = new {0}();", ThisED.ClassNames.Dto());
            //        ThisProcedure.Body.Add("    if (TimeStampColumnIndex != -1) ThisDto.TimeStamp = (byte[])sqlDataReader.GetValue(TimeStampColumnIndex);");
            //        ThisProcedure.Body.AddBlankLine();
            //        foreach (var ThisPD in ThisED.PropertyDefs.ScalarOrEntityProperties)
            //        {
            //            dynamic ColumnIndex = ThisPD.DatabaseColumnName + "ColumnIndex";
            //            string SqlDataReaderGet = null;
            //            if (ThisPD.IsEntityType)
            //                SqlDataReaderGet = "GetGuid";
            //            else
            //                SqlDataReaderGet = ThisPD.SqlDataReaderGet;
            //            if (ThisPD.IsNullable)
            //            {
            //                ThisProcedure.Body.Add("    if ({0} != -1)", ColumnIndex);
            //                ThisProcedure.Body.Add("    {");
            //                ThisProcedure.Body.Add("        if (sqlDataReader.IsDBNull({0}))", ColumnIndex);
            //                ThisProcedure.Body.Add("            ThisDto.{0} = null;", ThisPD.Names.Field());
            //                ThisProcedure.Body.Add("        else");
            //                ThisProcedure.Body.Add("            ThisDto.{0} = sqlDataReader.{1}({2});", ThisPD.Names.Field(), SqlDataReaderGet, ColumnIndex);
            //                ThisProcedure.Body.Add("    }");
            //            }
            //            else
            //            {
            //                ThisProcedure.Body.Add("    if ({2} != -1) ThisDto.{0} = sqlDataReader.{1}({2});", ThisPD.Names.Field(), SqlDataReaderGet, ColumnIndex);
            //            }
            //        }
            //        ThisProcedure.Body.AddBlankLine();
            //        ThisProcedure.Body.Add("    items.Add(ThisDto);");

            //        ThisProcedure.Body.Add("}");                    
            //    }



            //}

            //#endregion

            //#region AddGetColumnIndexProcedure


            //private void AddGetColumnIndexProcedure()
            //{
            //    var ThisProcedure = this.AddRegion("GetColumnIndex").AddProcedure("GetColumnIndex", Modifier.Private, "int");
            //    ThisProcedure.Documentation.Summary = "Searches the identified SQL Data Reader for a column with the identified name.  If one is not found, -1 is returned.";
            //    ThisProcedure.Parameters.Add("sqlDataReader", "SqlDataReader");
            //    ThisProcedure.Parameters.Add("DatabaseColumnName", "string");
            //    ThisProcedure.Body.Add("int FoundIndex = -1;");
            //    ThisProcedure.Body.Add("for (int columnIndex = 0; columnIndex < sqlDataReader.FieldCount; columnIndex++)");
            //    ThisProcedure.Body.Add("{");
            //    ThisProcedure.Body.Add("    if (sqlDataReader.GetName(columnIndex)==DatabaseColumnName)");
            //    ThisProcedure.Body.Add("    {");
            //    ThisProcedure.Body.Add("        FoundIndex = columnIndex;");
            //    ThisProcedure.Body.Add("        break;");
            //    ThisProcedure.Body.Add("    }");
            //    ThisProcedure.Body.Add("}");
            //    //.Add("if (FoundIndex == -1) throw new Exception(""Unable to find column '"" + DatabaseColumnName + ""' in '"" + tableName + ""' table."");")

            //    ThisProcedure.Body.Add("return FoundIndex;");
            //}

            //#endregion
        }

        #endregion
    }
}
